/*
 * Copyright (c) 2011 Imre Fazekas.
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of the Brillien nor the names of its
 * terms and concepts may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.vii.brillien.kernel.axiom.transport;

import com.vii.brillien.kernel.BrillienException;
import com.vii.brillien.kernel.axiom.sso.Session;

import java.util.HashMap;
import java.util.Map;


/**
 * Mediator type to collect all communication sending request invoked by Presences and to delegate to the communication realizing subsystem.
 */
public interface Mediator<C extends Communication, T> {

    /**
     * Sets up the connection with the underlaying transport layer
     */
    void connect() throws BrillienException;

    /**
     * Dismisses the connection with the underlaying transport layer
     */
    void disconnect() throws BrillienException;

    /**
     * Initiates the internal listening process of the given Mediator to start accept incoming packets
     */
    void startListening( ) throws BrillienException;

    /**
     * Registers a MessageProcessor type
     */
    <M extends MessageProcessor> void addMessageProcessorType(Class<M> messageProcessorType);

    /**
     * Registers a MessageProcessor inner class type with the outer class instance
     */
    <M extends MessageProcessor> void addMessageProcessorType(Class<M> messageProcessorType, Object outerInstance);

    /**
     * Creates an instances of evety registered MessageProcessor type and initiates them with the give Communication
     */
    <M extends MessageProcessor> Iterable<M> getNewMessageProcessorInstances(C comm) throws BrillienException;


    /**
     * Registers a CommunicationListener
     */
    <M extends CommunicationListener<T>> void addCommunicationListener(M messageProcessor);

    /**
     * Deregisters a CommunicationListener
     */
    <M extends CommunicationListener<T>> void removeCommunicationListener(M messageProcessor);

    /**
     * Retrieves the list of registered CommunicationListeners
     */
    Iterable<CommunicationListener<T>> getCommunicationListeners( );


    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication( ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            String sender, String flowID, String recipient, String subject, int type
    ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            C comm, String sender, String flowID, String recipient, String subject, int type
    ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            Session session, String sender, String flowID, String recipient, String subject, int type
    ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            Session session, C comm, String sender, String flowID, String recipient, String subject, int type
    ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            String sender, String flowID, String recipient, String subject, int type, Map<String, Object> parameters
    ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            C comm, String sender, String flowID, String recipient, String subject, int type, Map<String, Object> parameters
    ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            Session session, String sender, String flowID, String recipient, String subject, int type, Map<String, Object> parameters
    ) throws BrillienException;

    /**
     * Factory method to initiate a communication
     */
    C prepareNewCommunication(
            Session session, C comm, String sender, String flowID, String recipient, String subject, int type, Map<String, Object> parameters
    ) throws BrillienException;

    /**
     * Retrieves the name of the current mediator's entity
     */
    String mediatorEntity( );


    /**
     * Sends a message.
     */
    C sendCommunication(C comm) throws BrillienException;

    /**
     * Sends a message.
     */
    C sendCommunication(HashMap<String, Object> properties, C comm) throws BrillienException;

    /**
     * Sends a packet. Waiting for response for the given amount of time
     */
    C sendCommunication( long timeout, C comm) throws BrillienException;

    /**
     * Sends a packet. Waiting for response for the given amount of time
     */
    C sendCommunication( long timeout, HashMap<String, Object> properties, C comm) throws BrillienException;

    /**
     * Special entry point allowing to put insider messages into the Mediator
     */
    void receiveCommunication(C comm) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will not return until the response is arrived or a timeout event occured.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    C sendGet( Session session, String to, String message ) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will not return until the response is arrived or a timeout event occured.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    C sendGet( Session session, long timeout, String to, String message ) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will return immediately after having sent the message. The response will sent to this Aspirer through the given redirectMessage.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    void sendAGet( Session session, String to, String message, String redirectMessage ) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will return immediately after having sent the message. The response will sent to this Aspirer through the given redirectMessage.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    void sendDelegatedGet( Session session, String to, String message, String redirectEntityName, String redirectMessage ) throws BrillienException;

    /**
     * Sends a set-like message to the given recipient. The method will return immediately after having sent the message, no response is expected.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    void sendSet( Session session, String to, String message ) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will not return until the response is arrived or a timeout event occured.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    C sendGet( Session session, String to, String message, Map<String, Object> parameters ) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will not return until the response is arrived or a timeout event occured.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    C sendGet( Session session, long timeout, String to, String message, Map<String, Object> parameters ) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will return immediately after having sent the message. The response will sent to this Aspirer through the given redirectMessage.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    void sendAGet( Session session, String to, String message, String redirectMessage, Map<String, Object> parameters ) throws BrillienException;

    /**
     * Sends a get-like message to the given recipient. The method will return immediately after having sent the message. The response will sent to this Aspirer through the given redirectMessage.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    void sendDelegatedGet( Session session, String to, String message, String redirectEntityName, String redirectMessage, Map<String, Object> parameters ) throws BrillienException;

    /**
     * Sends a set-like message to the given recipient. The method will return immediately after having sent the message, no response is expected.
     * The parameters will be converted to Json format. In case of unsuccessful conversion, an exception will be thrown.
     */
    void sendSet( Session session, String to, String message, Map<String, Object> parameters ) throws BrillienException;

}
